package typedefault

import (
	"codejy/analysis"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/utils"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

type Http struct {
	Addr        string
	ThreadStore *structdef.ThreadStore
	Http        *utils.HttpClient
}

// 创建实例
func (a *Http) CreateTypeDefault(addr string, threadStore *structdef.ThreadStore, parameter ...string) {
	instance := &Http{
		Addr:        addr,
		ThreadStore: threadStore,
		Http:        utils.NewHttpClient(),
	}
	instance.Http.SkipVerify() //跳过https证书验证
	store.AddTypeDefaultInstanceStore(threadStore, a.GetTypeName(), addr, instance)
}
func (a *Http) ParameterProcessing(parameter []string) []string {
	//排除前后""
	for i := range parameter {
		s := parameter[i]
		if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
			s = s[1 : len(s)-1]
			parameter[i] = s
		}
	}
	return parameter
}

func (a *Http) GetData() interface{} {
	return a.Http
}

func (a *Http) ToStr() string {
	return ""
}

// 添加请求url
func (a *Http) AddUrl(url string) string {
	a.Http.AddUrl(url)
	return a.Addr
}

// 设置请求超时时间,单位秒
func (a *Http) SetTimeout(timeout string) string {
	//将字符串转换为int
	timeoutInt, p := strconv.Atoi(timeout)
	if p != nil {
		panic("Http-setTimeout(?)参数错误,必须是整数")
	}
	a.Http.SetTimeout(time.Duration(timeoutInt) * time.Second)
	return a.Addr
}

// 添加代理,"http://proxy-server-address:port"   用户密码可以为""
func (a *Http) AddProxy(proxyUrl, username, password string) string {
	a.Http.AddProxy(proxyUrl, username, password)
	return a.Addr
}

// 添加请求头
func (a *Http) AddHeader(key, value string) string {
	a.Http.AddHeader(key, value)
	return a.Addr
}

// 添加请求参数
func (a *Http) AddParam(key, value string) string {
	a.Http.AddParams(key, value)
	return a.Addr
}

// 添加请求参数
func (a *Http) AddFormData(key, value string) string {
	a.Http.AddFormData(key, value)
	return a.Addr
}

// 添加body
func (a *Http) AddBody(body string) string {
	//验证是否是json格式
	if !utils.IsValidJSON(body) {
		panic("Http-body(?)参数错误,必须是json格式")
	}
	a.Http.AddData(body)
	return a.Addr
}

// get请求
func (a *Http) Get() string {
	a.Http.Get()
	return a.Addr
}

// post请求
func (a *Http) Post() string {
	a.Http.Post()
	return a.Addr
}

// put请求
func (a *Http) Put() string {
	a.Http.Put()
	return a.Addr
}

// delete请求
func (a *Http) Delete() string {
	a.Http.Delete()
	return a.Addr
}

// 上传文件
func (a *Http) UploadFile(fileKey, filePath string) {
	a.Http.UploadFile(fileKey, filePath)
}

// 批量上传文件
func (a *Http) UploadFiles(fileKey string, filePaths string) {
	//如果是List,那么打印出来
	value, b := GetTypeDefaultValue[[]string](a.ThreadStore, "List", filePaths)
	if !b {
		panic("Http-uploadFiles(?)参数错误,必须是List类型")
	}
	a.Http.UploadFiles(fileKey, value)
}

// 下载文件
func (a *Http) DownloadFile(filePath string) {
	a.Http.DownloadFile(filePath)
}

// 异步
func (a *Http) Async(funcName string) {
	//获取函数定义,函数定义是在当前文件中定义的
	definition := store.SearchFunDefinition(a.ThreadStore, funcName)
	if definition == nil {
		panic("函数" + funcName + "未定义")
	}
	group := globalfunc.ExecuteFunc("GetThreadAllWait").(*sync.WaitGroup)
	group.Add(1)
	a.Http.Async(func(str string, err error) {
		defer func() {
			if err1 := recover(); err1 != nil {
				store.PrintExecuteCodeRecordLog(a.ThreadStore, err1)
				os.Exit(1)
			}
		}()
		if err != nil {
			panic(err)
		}
		str = analysis.AddDoubleQuotationMarks2(str)
		globalfunc.ExecuteFunc("FunLineExecute", a.ThreadStore, definition.Body, "", definition.Name, []string{str})
		//globalfunc.ExecuteFunc("NewThreadInside", a.ThreadStore, funcName, []string{str})
		group.Done()
	})
}

// 同步 ,发送请求
func (a *Http) Send() string {
	sync, err := a.Http.Sync()
	if err != nil {
		panic(err)
	}
	return sync
}

func (f *Http) GetDef() string {
	return `
    	@CodeManual(def="new("Http")",des="创建Http实例")
		type Http{
			def init{
				core&CreateTypeDefault()
			}
			@CodeManual(def="url($1)",des="添加请求url")
			def url{
				to core&AddUrl($1)
			}
			@CodeManual(def="timeout($1)",des="设置请求超时时间,单位秒")
			def timeout{
				to core&SetTimeout($1)
			}
			@CodeManual(def="proxy($1,$2,$3)",des="添加代理,$1:代理地址,$2:用户名(不是必须的),$3:密码(不是必须的)")
			def proxy{
				to core&AddProxy($1,$2,$3)
			}
			@CodeManual(def="header($1,$2)",des="添加请求头,$1:键,$2:值")
			def header{
				to core&AddHeader($1,$2)
			}

			@CodeManual(def="param($1,$2)",des="添加请求参数,$1:键,$2:值")
			def param{
				to core&AddParam($1,$2)
			}
			@CodeManual(def="formData($1,$2)",des="添加请求参数,$1:键,$2:值")
			def formData{
				to core&AddFormData($1,$2)
			}

			@CodeManual(def="body($1)",des="添加body,$1:json格式")
			def body{
				to core&AddBody($1)
			}
			@CodeManual(def="get()",des="get请求")
			def get{
				to core&Get()
			}
			@CodeManual(def="post()",des="post请求")
			def post{
				to core&Post()
			}
			@CodeManual(def="put()",des="put请求")
			def put{
				to core&Put()
			}
			@CodeManual(def="delete()",des="delete请求")
			def delete{
				to core&Delete()
			}
			@CodeManual(def="send()",des="同步发送请求,返回结果")
			def send{
				to core&Send()
			}
			@CodeManual(def="asyncSend($1)",des="异步发送请求,$1:回调函数")
			def asyncSend{
				core&Async($1)
			}
			@CodeManual(def="uploadFile($1,$2)",des="上传文件,$1:文件key,$2:文件路径")
			def uploadFile{
				core&UploadFile($1,$2)	
			}
			@CodeManual(def="uploadFiles($1,$2)",des="批量上传文件,$1:文件key,$2:文件路径List")
			def uploadFiles{
				core&UploadFiles($1,$2)
			}

			@CodeManual(def="downloadFile($1)",des="下载文件,$1:文件路径")
			def downloadFile{
				core&DownloadFile($1)
			}
		
		}
	`
}
func init() {
	RegisterTypeDefault(&Http{})
}

func (f *Http) GetTypeName() string {
	return "Http"
}
